package cn.tnar.parkservice.service.impl;

import cn.tnar.parkservice.config.Constant;
import cn.tnar.parkservice.config.ExportConstant;
import cn.tnar.parkservice.mapper.TCalendarMapper;
import cn.tnar.parkservice.model.dto.CalendarDto;
import cn.tnar.parkservice.model.entity.TCalendar;
import cn.tnar.parkservice.service.ITCalendarService;
import cn.tnar.parkservice.util.DateUtils;
import cn.tnar.parkservice.util.ExcelUtil;
import cn.tnar.parkservice.util.common.ResultCode;
import cn.tnar.parkservice.util.common.ResultJson;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zzb
 * @since 2019-03-11
 */
@Service("tCalendarServiceImpl")
public class TCalendarServiceImpl extends ServiceImpl<TCalendarMapper, TCalendar> implements ITCalendarService {
    private ResultJson resultJson = new ResultJson();

    @Override
    public ResultJson query(MultipartFile file) {
        InputStream fis = null;
        try {
            fis = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Workbook wookbook = null;

        try {
            //2007版本的excel，用.xlsx结尾

            wookbook = new XSSFWorkbook(fis);//得到工作簿
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //得到一个工作表
        Sheet sheet = wookbook.getSheetAt(0);

        //获得数据的总行数
        int totalRowNum = sheet.getLastRowNum();

        if (totalRowNum == 0) {
            return resultJson.setCode(300).setMsg(Constant.MSG_EXCEL_NULL).setData(null);
        }
        Map<String, String> map = new HashMap<>();
        for (int i = 1; i <= totalRowNum; i++) {
            Row row = sheet.getRow(i);
            row.getCell((short) 0).setCellType(Cell.CELL_TYPE_STRING);
            String year = row.getCell((short) 0).getStringCellValue().substring(0, 4);
            map.put(year, year);
        }

        if (map.size() > 1) {
            return resultJson.setCode(300).setMsg(Constant.MSG_EXCEL_ONLY).setData(null);
        }


        for (String key : map.keySet()) {
            QueryWrapper<TCalendar> wrapper = new QueryWrapper<TCalendar>()
                    .eq("left(DATUMDATE,4)", key);
            List<TCalendar> list = this.list(wrapper);

            if (list.size() > 0) {
                return resultJson.setCode(200).setMsg(Constant.MSG_EXCEL_EXISTS).setData(key);
            } else {
                return resultJson.setCode(900).setMsg(Constant.MSG_EXCEL_NOEXISTS).setData(null);

            }
        }


        return null;
    }

    @Override
    public void downCal(HttpServletResponse response, int year) {
        List<TCalendar> list = getDays(year);

        //excel标题
        String[] title = ExportConstant.CALENDAR_TITLE;

        //excel文件名
        String fileName = year + "计费日历导入模版.xlsx";

        //sheet名
        String sheetName = year + "年";
        String[][] content = new String[list.size()][];
        for (int i = 0; i < list.size(); i++) {
            TCalendar tCalendar = list.get(i);
            content[i] = new String[title.length];
            content[i][0] = tCalendar.getDatumdate();
            content[i][1] = String.valueOf(tCalendar.getWeekday());
            content[i][2] = tCalendar.getHoliday();


        }
        //创建HSSFWorkbook
        XSSFWorkbook wb = ExcelUtil.getXSSFWorkbook(sheetName, title, content, null);

        //响应到客户端
        try {
            this.setResponseHeader(response, fileName);
            OutputStream os = response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public ResultJson excelInCal(MultipartFile file) {
        String filePath = file.getOriginalFilename();
        if (!filePath.endsWith(".xls") && !filePath.endsWith(".xlsx")) {

            return resultJson.setCode(900).setMsg(Constant.MSG_EXCEL_TYPE).setData(null);

        }
        InputStream fis = null;
        try {
            fis = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Workbook wookbook = null;

        try {
            //2007版本的excel，用.xlsx结尾

            wookbook = new XSSFWorkbook(fis);//得到工作簿
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //得到一个工作表
        Sheet sheet = wookbook.getSheetAt(0);

        //获得数据的总行数
        int totalRowNum = sheet.getLastRowNum();


        //要获得属性
        Map<String, String> map = new HashMap<>();
        for (int i = 1; i <= totalRowNum; i++) {
            Row row = sheet.getRow(i);
            row.getCell((short) 0).setCellType(Cell.CELL_TYPE_STRING);
            String substring = row.getCell((short) 0).getStringCellValue().substring(0, 4);
            map.put(substring, substring);
        }
        if (map.size() > 1) {
            return resultJson.setCode(900).setMsg(Constant.MSG_EXCEL_ONLY).setData(null);
        }


        for (String key : map.keySet()) {
            QueryWrapper<TCalendar> wrapper = new QueryWrapper<TCalendar>()
                    .eq("left(DATUMDATE,4)", key);
            this.remove(wrapper);
        }


        List<TCalendar> list = new ArrayList<>();
        for (int i = 1; i <= totalRowNum; i++) {
            Row row = sheet.getRow(i);
            if (row.getCell((short) 0) != null) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String nowStr = sdf.format(new Date());

                TCalendar tCalendar = new TCalendar();
                tCalendar.setUpdatetime(nowStr);
                //获得获得第i行第0列的 String类型对象
                try {
                    row.getCell((short) 0).setCellType(Cell.CELL_TYPE_STRING);
                    row.getCell((short) 1).setCellType(Cell.CELL_TYPE_STRING);
                    row.getCell((short) 2).setCellType(Cell.CELL_TYPE_STRING);

                    String DATUMDATE = row.getCell((short) 0).getStringCellValue();
                    String WEEKDAY = row.getCell((short) 1).getStringCellValue();
                    String HOLIDAY = row.getCell((short) 2).getStringCellValue();
                    int weekDay = Integer.parseInt(WEEKDAY);
                    if (weekDay > 6 || weekDay < 0) {
                        return resultJson.setCode(900).setMsg("导入失败,请核对第" + i + "行数据").setData(null);
                    }
                    if (!HOLIDAY.equals("Y") && !HOLIDAY.equals("N")) {
                        return resultJson.setCode(900).setMsg("导入失败,请核对第" + i + "行数据").setData(null);
                    }
                    tCalendar.setHoliday(HOLIDAY);
                    tCalendar.setWeekday(Integer.parseInt(WEEKDAY));
                    tCalendar.setDatumdate(DATUMDATE);
                    list.add(tCalendar);

                } catch (Exception e) {
                    e.printStackTrace();
                    return resultJson.setCode(900).setMsg(Constant.MSG_EXCEL_SPACE).setData(null);
                }
            }
        }

        boolean b = false;

        if (list == null) {
            return resultJson.setCode(900).setMsg(Constant.MSG_EXCEL_NULL).setData(null);
        }
        if (list.size() > 0) {
            b = this.saveBatch(list);
        } else {
            return resultJson.setCode(900).setMsg(Constant.MSG_EXCEL_NULL).setData(null);
        }


        if (b) {
            return resultJson.setCode(200).setMsg(ResultCode.SUCCESS_MSG).setData(null);
        } else {
            return resultJson.setCode(900).setMsg(ResultCode.FAIL_MSG).setData(null);
        }
    }

    @Override
    public ResultJson queryCal(String json) {
        CalendarDto calendar = JSON.parseObject(json, CalendarDto.class);
        if (calendar.getYear() == null) {
            return resultJson.setData(null).setMsg(Constant.MSG_YEAR_ERROR).setCode(ResultCode.FAIL);
        }
        QueryWrapper<TCalendar> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("LEFT(DATUMDATE,4)", calendar.getYear());
        List<TCalendar> list = this.list(queryWrapper);
        return resultJson.setData(list).setMsg(ResultCode.SUCCESS_MSG).setCode(ResultCode.SUCCESS);
    }

    //发送响应流方法
    public void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            response.reset();
            response.setContentType("application/ms-excel");
            response.setCharacterEncoding("utf-8");

            try {
                fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    public List<TCalendar> getDays(int year) {
        List<TCalendar> list = new ArrayList<>();
        for (int i = 1; i < 13; i++) {

            String first = DateUtils.getFirstDayOfMonth(year, i);
            String last = DateUtils.getLastDayOfMonth(year, i);
            int days = Integer.parseInt(last.substring(8, 10)) - Integer.parseInt(first.substring(8, 10));
            for (int j = 0; j < days + 1; j++) {

                TCalendar tCalendar = new TCalendar();
                String day = String.valueOf(Integer.parseInt(first.substring(8, 10)) + j);
                String strDay = StringUtils.leftPad(day, 2, "0");

                tCalendar.setDatumdate(first.substring(0, 8) + strDay);

                int week = Integer.parseInt(getDayOfWeekByDate(first.substring(0, 8) + strDay));
                tCalendar.setWeekday(week);
                if (week == 6 || week == 0) {
                    tCalendar.setHoliday("Y");
                } else {
                    tCalendar.setHoliday("N");
                }
                list.add(tCalendar);
            }

        }


        return list;

    }

    public static String getDayOfWeekByDate(String date) {
        String dayOfweek = "-1";
        try {
            SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
            Date myDate = myFormatter.parse(date);
            SimpleDateFormat formatter = new SimpleDateFormat("E");
            String str = formatter.format(myDate);
            dayOfweek = str;

        } catch (Exception e) {
            e.printStackTrace();

        }
        switch (dayOfweek) {
            case "Mon":
            case "星期一":
                dayOfweek = "1";
                break;
            case "Tue":
            case "星期二":
                dayOfweek = "2";
                break;
            case "Wed":
            case "星期三":
                dayOfweek = "3";
                break;
            case "Thu":
            case "星期四":
                dayOfweek = "4";
                break;
            case "Fri":
            case "星期五":
                dayOfweek = "5";
                break;
            case "Sat":
            case "星期六":
                dayOfweek = "6";
                break;
            case "Sun":
            case "星期日":
                dayOfweek = "0";
                break;

            default:
                dayOfweek = "7";
                break;
        }

        return dayOfweek;
    }
}
